package com.lilihub.miaosha.controller;

import com.lilihub.miaosha.common.CodeMsg;
import com.lilihub.miaosha.common.Result;
import com.lilihub.miaosha.domain.MiaoshaOrder;
import com.lilihub.miaosha.domain.MiaoshaUser;
import com.lilihub.miaosha.intercepter.AccessLimit;
import com.lilihub.miaosha.rabbitmq.MQSender;
import com.lilihub.miaosha.rabbitmq.MiaoshaMessage;
import com.lilihub.miaosha.redis.AccessKey;
import com.lilihub.miaosha.redis.GoodKey;
import com.lilihub.miaosha.redis.MiaoshaKey;
import com.lilihub.miaosha.redis.OrderKey;
import com.lilihub.miaosha.service.GoodsService;
import com.lilihub.miaosha.service.MiaoshaService;
import com.lilihub.miaosha.service.OrderService;
import com.lilihub.miaosha.service.RedisService;
import com.lilihub.miaosha.util.MD5Util;
import com.lilihub.miaosha.util.UUIDUtil;
import com.lilihub.miaosha.vo.GoodsVo;
import com.sun.corba.se.spi.servicecontext.UEInfoServiceContext;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.CommonDataSource;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static javax.imageio.ImageIO.write;

/**
 * @BelongsProject: miaosha
 * @BelongsPackage: com.lilihub.miaosha.controller
 * @Author: LiYing
 * @CreateTime: 2021-04-27 11:18
 * @Description:
 */

@Controller
@RequestMapping("/miaosha")
public class MiaoshaController implements InitializingBean {


    @Autowired
    private GoodsService goodsService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private MQSender mqSender;


    @Autowired
    private MiaoshaService miaoshaService;

    private Map<Long,Boolean> localOverMap = new HashMap<>();


    // 1 系统初始化，把商品库存数量加载到Redis
    @Override
    public void afterPropertiesSet() throws Exception {

        List<GoodsVo> goods = goodsService.getGoodsVoList();

        if (goods == null) {
            return;
        }

        for (GoodsVo goodsVo : goods) {
            redisService.set(GoodKey.getMiaoshaGoodStock, "" + goodsVo.getId(), goodsVo.getStockCount());
            localOverMap.put(goodsVo.getId(),false);
        }
    }


    @PostMapping("/{path}/do_miaosha")
    @ResponseBody
    public Result<Integer> miaosha(Model model, MiaoshaUser user,
                                   @RequestParam("goodsId") long goodsId,
                                   @PathVariable("path") String path) {


        if (user == null) {
            return Result.error(CodeMsg.USER_EMPTY);
        }

        //秒杀收到请求，先验证PathVariable
        boolean check = miaoshaService.checkPath(user,goodsId,path);
        if (!check){
            return Result.error(CodeMsg.REQUEST_ILLEAL);
        }

        //利用内存标记，减少redis访问
        Boolean over = localOverMap.get(goodsId);
        if (over){
            return Result.error(CodeMsg.MIAO_SHA_OVER);
        }

        // 2 收到请求，Redis预减库存，库存不足，直接返回，否则进入3
        Long stock = redisService.decr(GoodKey.getMiaoshaGoodStock, "" + goodsId);
        if (stock < 0) {
            localOverMap.put(goodsId,true);
            return Result.error(CodeMsg.MIAO_SHA_OVER);
        }

        // 判断用户是否已经秒杀到了---缓存中
        MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(), goodsId);
        if (order != null) {
            return Result.error(CodeMsg.REPEATE_MIAOSHA);
        }

        // 3 请求入队，立即返回排队中
        MiaoshaMessage msg = new MiaoshaMessage(user, goodsId);
        mqSender.sendMiaoshaMessage(msg);

        return Result.success(0);//0表示排队中



        /*
        //判断库存
        GoodsVo goods = goodsService.getGoodsByGoodsId(goodsId);  //10 req1 req2
        Integer stockCount = goods.getStockCount();

        if (stockCount <= 0){
            return Result.error(CodeMsg.MIAO_SHA_OVER);
        }

        //判断用户是否已经秒杀到了
        MiaoshaOrder order = orderService.getMiaoshaOrderByUserIdGoodsId(user.getId(),goodsId);
        if (order != null){
            return Result.error(CodeMsg.REPEATE_MIAOSHA);
        }

        //减库存 下订单 写入秒杀订单
        OrderInfo orderInfo = miaoshaService.miaosha(user,goods);

        return Result.success(orderInfo);

        *
         */
    }

    /**
     * 秒杀成功，则返回orderId
     * 秒杀失败，则返回-1
     * 排队中，则返回0
     */
    @AccessLimit(seconds = 5,maxCount=10,needLogin=true)
    @GetMapping("result")
    @ResponseBody
    public Result miaoshaResult(Model model, MiaoshaUser user,
                                @RequestParam("goodsId") long goodsId) {


        if (user == null) {
            return Result.error(CodeMsg.USER_EMPTY);
        }

        //客户端轮询，是否秒杀成功
        long result = miaoshaService.getMiaoshaResult(user.getId(), goodsId);

        return Result.success(result);

    }


    @GetMapping("reset")
    @ResponseBody
    public Result reset(Model model,MiaoshaUser user){

        List<GoodsVo> goodsVoList = goodsService.getGoodsVoList();
        for (GoodsVo goodsVo : goodsVoList){
            goodsVo.setStockCount(10);
            redisService.set(GoodKey.getMiaoshaGoodStock,""+goodsVo.getId(),10);
            localOverMap.put(goodsVo.getId(),false);

            redisService.delete(OrderKey.getMiaoshaOrderByUidGid,"" + user.getId() +  "_" + goodsVo.getId());
            redisService.delete(OrderKey.getMiaoshaOrderByUidGid,"" + user.getId() +  "_" + goodsVo.getId());
            redisService.delete(MiaoshaKey.isGoodsOver,"" + goodsVo.getId());
            redisService.delete(MiaoshaKey.isGoodsOver,"" + goodsVo.getId());
        }

        redisService.reset(goodsVoList);
        return Result.success(true);

    }


    //得到秒杀路径
    @AccessLimit(seconds = 5,maxCount=5,needLogin=true)
    @GetMapping("path")
    @ResponseBody
    public Result getMiaoshaPath(MiaoshaUser user,
                                 HttpServletRequest request,
                                 @RequestParam("goodsId") long goodsId,
                                 @RequestParam("verifyCode") int verifyCode) {

        if (user == null) {
            return Result.error(CodeMsg.USER_EMPTY);
        }


        //2 在获取秒杀路径的时候，验证验证码
        boolean check = miaoshaService.checkVerifyCode(user,goodsId,verifyCode);
        if (!check){
            return Result.error(CodeMsg.REQUEST_ILLEAL);
        }

        String path = miaoshaService.createMiaoshaPath(user,goodsId);

        return Result.success(path);

    }

    //1 添加生成验证码的接口
    @GetMapping("verifyCode")
    @ResponseBody
    public Result getMiaoshaVerifyCode(Model model, MiaoshaUser user,
                                       @RequestParam("goodsId") long goodsId,
                                       HttpServletResponse response) {

        model.addAttribute("user", user);
        if (user == null) {
            return Result.error(CodeMsg.USER_EMPTY);
        }

        BufferedImage image = miaoshaService.createMiaoshaVerifyCode(user,goodsId);


        try {
            ServletOutputStream out = response.getOutputStream();
            ImageIO.write(image,"JPEG",out);
            out.flush();
            out.close();
            return null;

        } catch (Exception e) {
            e.printStackTrace();

            return Result.error(CodeMsg.MIAOSHA_FAIL);
        }

    }


}